package com.nuoniu.sibanyun.controller.pay;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.nuoniu.sibanyun.common.constant.OrderConstant;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.config.YmlConfig;
import com.nuoniu.sibanyun.entity.SysCompany;
import com.nuoniu.sibanyun.entity.SysUser;
import com.nuoniu.sibanyun.entity.crm.*;
import com.nuoniu.sibanyun.entity.expenses.ExpensesPaymentOrder;
import com.nuoniu.sibanyun.service.ISysCompanyService;
import com.nuoniu.sibanyun.service.ISysUserService;
import com.nuoniu.sibanyun.service.crm.*;
import com.nuoniu.sibanyun.service.expenses.IExpensesBusinessOrderService;
import com.nuoniu.sibanyun.service.expenses.IExpensesPaymentOrderService;
import com.nuoniu.sibanyun.utils.WeXinUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static java.lang.System.load;
import static java.lang.System.out;

/**
 * @auther 小啊刚
 * @date 2020-07-18
 */
@Controller
@Log4j2
@Api(tags = "支付宝支付", value = "支付宝支付")
public class AliPayController {

    @Autowired
    private ICrmGoodsOrderService orderService;
    @Autowired
    private ICrmSecretKeyService secretKeyService;
    @Autowired
    private ISysCompanyService companyService;
    @Autowired
    private ICrmWebConfigService webConfigService;
    @Autowired
    private ICommissionRecordService commissionRecordService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ICrmGoodsService goodsService;
    @Autowired
    private IExpensesBusinessOrderService businessOrderService;
    @Autowired
    private IExpensesPaymentOrderService paymentOrderService;

    /**
     * 支付宝网站（电脑/手机）支付(充值业务)
     * @param response
     * @param orderId
     * @param body
     * @throws AlipayApiException
     * @throws IOException
     */
    @GetMapping("/sby/aliPay/getAliPayUrlFromPayment")
    @ApiOperation(value = "支付宝网站（电脑/手机）支付(充值业务)")
    @ResponseBody
    public void getAliPayUrlFromPayment(HttpServletResponse response, String orderId, String body) throws AlipayApiException, IOException{
        //支付宝配置
        CrmWebConfig config = webConfigService.getById(1);
        // 超时时间 可空
        String timeout_express = "5m";
        // 支付产品类型码 必填
        String product_code = "FAST_INSTANT_TRADE_PAY";
        //调用RSA2签名方式
        AlipayClient client = new DefaultAlipayClient(YmlConfig.URL, config.getAppId(), config.getMerchantPrivateKey(), YmlConfig.FORMAT, YmlConfig.CHARSET, config.getAlipayPublicKey(), YmlConfig.SIGNTYPE);
        AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();
        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        ExpensesPaymentOrder paymentOrder = paymentOrderService.getById(orderId);
        if(null == paymentOrder)throw new NuoNiuException("参数错误，请刷新页面");
        model.setOutTradeNo(paymentOrder.getOrderNo());
        BigDecimal paymentAmount = paymentOrder.getPaymentAmount();
        // 订单名称，必填
        model.setSubject("四班云账户充值");
        // 付款金额，必填
        if(paymentAmount != null && paymentAmount.compareTo(BigDecimal.ZERO) > 0 ) {
            model.setTotalAmount(paymentAmount.toString());
        }else {
            throw new NuoNiuException("此订单金额有问题，请核实");
        }
        // 商品描述，可空
        model.setBody(body);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(config.getNotifyUrl());
        // 设置同步地址
        alipay_request.setReturnUrl(config.getReturnUrl());
        // 调用SDK生成表单
        String form;
        form = client.pageExecute(alipay_request).getBody();
        response.setContentType("text/html;charset=" + YmlConfig.CHARSET);
        response.getWriter().write(form);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
        //用于测试

    }

    /**
     * 支付宝网站（电脑/手机）支付
     * @param orderId 订单id
     * @param subjectName 订单名称
     * @param totalAmount 订单总金额
     * @param body 订单详情
     * @author 小啊刚
     * @date 2020/07/18
     */
    @GetMapping("/sby/aliPay/getAliPayUrl")
    @ResponseBody
    public void getAliPayUrl(HttpServletResponse response, String orderId, String subjectName, String totalAmount, String body) throws AlipayApiException, IOException {
        //支付宝配置
        CrmWebConfig config = webConfigService.getById(1);
        // 超时时间 可空
        String timeout_express = "5m";
        // 支付产品类型码 必填
        String product_code = "FAST_INSTANT_TRADE_PAY";
        //调用RSA2签名方式
        AlipayClient client = new DefaultAlipayClient(YmlConfig.URL, config.getAppId(), config.getMerchantPrivateKey(), YmlConfig.FORMAT, YmlConfig.CHARSET, config.getAlipayPublicKey(), YmlConfig.SIGNTYPE);
        AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();
        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        model.setOutTradeNo(orderId + "X" + getValidateCode());
        CrmGoodsOrder order = orderService.getById(orderId);
        // 订单名称，必填
        model.setSubject(order.getGoodsName());
        // 付款金额，必填
        if(order != null && order.getSalePrice() != null && order.getSalePrice().compareTo(BigDecimal.ZERO) == 1) {
            model.setTotalAmount(order.getSalePrice().toString());
        }else {
            System.out.println("此订单金额有问题，请核实");
        }
        // 商品描述，可空
        model.setBody(body);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl("www");
        // 设置同步地址
        alipay_request.setReturnUrl(config.getReturnUrl());
        // 调用SDK生成表单
        String form;
        form = client.pageExecute(alipay_request).getBody();
        response.setContentType("text/html;charset=" + YmlConfig.CHARSET);
        response.getWriter().write(form);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
        //用于测试
//        updateOrder(orderId, 1);
    }


    /**
     * 支付宝支付结果异步通知
     * @author 小啊刚
     * @date 2019/11/18
     */
    @PostMapping("/auth/aliPay/resultNotify")
    @ResponseBody
    public void aliPayResultNotify(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException {
        System.out.println("=======支付宝结果异步通知 begin======");
        //支付宝配置
        CrmWebConfig config = webConfigService.getById(1);
        Map<String, String> params = new HashMap();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            //System.out.println("valueStr = " + valueStr);
            params.put(name, valueStr);
        }
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号
        String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        //支付宝交易号
        String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        //交易状态
        String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        //买家支付账号
        //String buyerLogonId = new String(request.getParameter("buyer_logon_id").getBytes("ISO-8859-1"), "UTF-8");
        //买家实付金额
        //String buyerPayAmount = new String(request.getParameter("buyer_pay_amount").getBytes("ISO-8859-1"), "UTF-8");
        //商家实收金额
        //String receiptAmount = new String(request.getParameter("receipt_amount").getBytes("ISO-8859-1"), "UTF-8");
        //订单金额
        //String totalAmount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
        //计算得出通知验证结果
        boolean verifyResult = AlipaySignature.rsaCheckV1(params, config.getAlipayPublicKey(), YmlConfig.CHARSET, "RSA2");
        log.info("verify_result = " + verifyResult + ", trade_status =" + tradeStatus);
        if(verifyResult) { //验证成功
            if(outTradeNo.startsWith(OrderConstant.PAYMENT_PRE )){
                ExpensesPaymentOrder expensesPaymentOrder = paymentOrderService.getByOrderNo(outTradeNo);
                expensesPaymentOrder.setStatus(1);
                expensesPaymentOrder.setPaymentProof(tradeNo);
                expensesPaymentOrder.setPaymentType(2);  //支付方式 1：微信 2：支付宝
                expensesPaymentOrder.setPaymentTime(LocalDateTime.now());
                expensesPaymentOrder.setCallBackJson(JSON.toJSONString(params));
                paymentOrderService.successPayment(expensesPaymentOrder);
            }else{
                String orderId = outTradeNo.split("X")[0];
//                updateOrder(orderId, 1);
            }
            PrintWriter writer = null;
            try {
                writer =  response.getWriter();
                writer.write("success");
                writer.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(writer != null) {
                    writer.close();
                }
            }
            out.println("success");	//请不要修改或删除
            out.close();
        }else {//验证失败
            out.println("fail");
        }
    }

    /**
     * 微信支付回调
     * @author 小啊刚
     * @date 2020-08-21
     */
    @PostMapping("auth/wxPay/resultNotify")
    public String resultNotify(@RequestBody String notifyData, HttpServletResponse response) throws Exception {
        log.info("======微信异步回调通知=======" + notifyData);
        Map<String, String> result = WeXinUtils.resultNotify(notifyData);
        if(result == null) {
            return null;
        }
        String orderId = result.get("out_trade_no");
        String tradeNo = result.get("trade_no");
        if(orderId.startsWith(OrderConstant.PAYMENT_PRE )){
            ExpensesPaymentOrder expensesPaymentOrder = paymentOrderService.getByOrderNo(orderId);
            expensesPaymentOrder.setStatus(1);
            expensesPaymentOrder.setPaymentProof(tradeNo);
            expensesPaymentOrder.setPaymentType(1);  //支付方式 1：微信 2：支付宝
            expensesPaymentOrder.setPaymentTime(LocalDateTime.now());
            expensesPaymentOrder.setCallBackJson(JSON.toJSONString(result));
            paymentOrderService.successPayment(expensesPaymentOrder);
        }else{
//            updateOrder(orderId, 2);
        }
        //返回给微信处理结果
        String resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        response.setContentType("text/xml");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
        return resXml;
    }

//    /**
//     * 处理支付后的业务
//     * @author 小啊刚
//     * @date 2020-08-21
//     */
//    public void updateOrder(String orderId, Integer payType) {
//        CrmGoodsOrder order = orderService.getById(orderId);
//        if(order.getOrderStatus()) {
//            log.info("=====此订单已经支付过=====" + "id=" + orderId);
//            return;
//        }
//        SysCompany company = companyService.getById(order.getCompanyId());
//        //保存密钥
//        CrmSecretKey secretKey = null;
//        if(order.getSecretKeyId() != null) {
//            secretKey = secretKeyService.getById(order.getSecretKeyId());
//            if(order.getUsers() != null && order.getUsers() > 0) {
//                secretKey.setUsers(secretKey.getUsers() + order.getUsers());
//            }
//            if(order.getYears() != null && order.getYears() > 0) {
//                secretKey.setYears(secretKey.getYears() + order.getYears());
//                secretKey.setEndDate(secretKey.getEndDate().plusYears(order.getYears()));
//            }
//            secretKeyService.updateById(secretKey);
//        } else {
//            secretKey = new CrmSecretKey();
//            secretKey.setSecretKey(secretKeyService.getBySecretKey());
//            secretKey.setTimes(1);
//            secretKey.setUseTimes(1);
//            secretKey.setUsers(order.getUsers());
//            secretKey.setYears(order.getYears());
//            secretKey.setGoodsId(order.getGoodsId());
//            secretKey.setGoodsName(order.getGoodsName());
//            secretKey.setUseDate(LocalDateTime.now());
//            secretKey.setType(1);
//            secretKey.setEndDate(LocalDateTime.now().plusYears(order.getYears()));
//            //首次购买奖励上级
//            try{
//                secretKeyService.save(secretKey);
//            }catch (Exception e) {
//                e.printStackTrace();
//            }
//
//            try{
//                if(company.getSecretKeyId() != null) {
//                    CrmSecretKey key = secretKeyService.getById(company.getSecretKeyId());
//                    if(key != null && key.getType() == 0) {
//                        rewardShareUser(company, order.getSalePrice(), order);
//                    }
//                }else {
//                    rewardShareUser(company, order.getSalePrice(), order);
//                }
//            }catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        //修改订单
//        order.setPayType(payType);
//        order.setSecretKey(secretKey.getSecretKey());
//        order.setSecretKeyId(secretKey.getId().intValue());
//        order.setOrderStatus(true);
//        order.setPayDate(LocalDateTime.now());
//        orderService.updateById(order);
//        //使用密钥
//        company.setSecretKey(secretKey.getSecretKey());
//        company.setSecretKeyId(secretKey.getId().intValue());
//        company.setCompanyUser(secretKey.getUsers());
//        companyService.updateById(company);
//        //扫描支付后 更新业务订单
//        businessOrderService.updateByCrmGoodsOrder(order);
//    }
//
//    /**
//     * 奖励上级用户
//     * @author 小啊刚
//     * @date 2020-07-27
//     */
//    @Async
//    public void rewardShareUser(SysCompany company, BigDecimal buyerPayAmount, CrmGoodsOrder order) {
//        CrmGoods goods = goodsService.getById(order.getGoodsId());
//        if(company.getShareUserId() != null && goods.getFirstReward() != null && goods.getFirstReward() > 0 && goods.getIsReward()) {
//            String orderNo = order.getOrderNo();
//            SysUser firstUser = userService.getById(company.getShareUserId());
//            if(firstUser != null) { //奖励第一级
//                BigDecimal firstReward = buyerPayAmount.multiply(new BigDecimal(goods.getFirstReward()).multiply(new BigDecimal(0.01)));
//                firstUser.setTotalCommission(firstUser.getTotalCommission().add(firstReward));
//                userService.updateById(firstUser);
//                //保存第一级奖励记录
//                saveCommissionRecord(company.getCompanyName(), orderNo, buyerPayAmount, goods.getFirstReward(), 1, firstReward, firstUser);
//                if(firstUser.getShareUserId() != null && goods.getSecondReward() != null && goods.getSecondReward() > 0) { //奖励第二级
//                    SysUser secondUser = userService.getById(firstUser.getShareUserId());
//                    BigDecimal secondReward = buyerPayAmount.multiply(new BigDecimal(goods.getSecondReward()).multiply(new BigDecimal(0.01)));
//                    secondUser.setTotalCommission(secondUser.getTotalCommission().add(secondReward));
//                    userService.updateById(secondUser);
//                    //保存第二级奖励记录
//                    saveCommissionRecord(company.getCompanyName(), orderNo, buyerPayAmount, goods.getSecondReward(), 2, secondReward, secondUser);
//                    if(secondUser.getShareUserId() != null && goods.getThirdReward() != null && goods.getThirdReward() > 0) { //奖励第三级
//                        SysUser thirdUser = userService.getById(secondUser.getShareUserId());
//                        BigDecimal thirdReward = buyerPayAmount.multiply(new BigDecimal(goods.getThirdReward()).multiply(new BigDecimal(0.01)));
//                        thirdUser.setTotalCommission(secondUser.getTotalCommission().add(thirdReward));
//                        userService.updateById(thirdUser);
//                        //保存第三级奖励记录
//                        saveCommissionRecord(company.getCompanyName(), orderNo, buyerPayAmount, goods.getThirdReward(), 3, thirdReward, thirdUser);
//                        if(thirdUser.getShareUserId() != null && goods.getFourthReward() != null && goods.getFourthReward() > 0) { //奖励第四级
//                            SysUser fourthUser = userService.getById(thirdUser.getShareUserId());
//                            BigDecimal fourthReward = buyerPayAmount.multiply(new BigDecimal(goods.getFourthReward()).multiply(new BigDecimal(0.01)));
//                            fourthUser.setTotalCommission(secondUser.getTotalCommission().add(fourthReward));
//                            userService.updateById(fourthUser);
//                            //保存第四级奖励记录
//                            saveCommissionRecord(company.getCompanyName(), orderNo, buyerPayAmount, goods.getFourthReward(), 4, fourthReward, fourthUser);
//                        }
//                    }
//                }
//            }
//        }
//    }
//
//    /**
//     * 保存佣金记录
//     * @author 小啊刚
//     * @date 2020-07-28
//     */
//    public void saveCommissionRecord(String companyName, String orderNo, BigDecimal buyerPayAmount, Integer rewardRate, Integer level, BigDecimal income, SysUser user) {
//        CommissionRecord record =  new CommissionRecord();
//        record.setOrderNo(orderNo);
//        record.setUserId(user.getId().intValue());
//        record.setUserName(user.getRealName());
//        record.setPayAmount(buyerPayAmount);
//        record.setRewardRate(rewardRate);
//        record.setRewardLevel(level);
//        record.setCompanyName(companyName);
//        record.setRewardIncome(income);
//        record.setTotalIncome(user.getTotalCommission());
//        record.setBalance(user.getTotalCommission().subtract(user.getWithdrawalCommission()));
//        commissionRecordService.save(record);
//    }

    /**
     * 获取4位长度验证码
     * @author 小啊刚
     * @date 2020-07-18
     */
    public static String getValidateCode() {
        String[] array = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < 4; i++) {
            int index = (int)(Math.random()*(array.length));
            buf.append(array[index]);
        }
        return buf.toString();
    }
}
